import { getFullUrl } from './url'

export async function get<T = any>(url: string) {
  const res = await new Promise<ApiResult<T>>((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    url = getFullUrl(url)
    url = url + (url.includes('?') ? '&' : '?') + '_=' + Date.now()
    xhr.open('GET', url)
    // IE 不支持 json 类型
    xhr.responseType = 'json'
    // IE9+
    if ('onload' in XMLHttpRequest.prototype) {
      xhr.onload = function () {
        resolve(getResponseJson(xhr))
      }
      xhr.onerror = function () {
        reject(new Error(`Error ${xhr.status}: ${xhr.statusText}`))
      }
    } else {
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          resolve(getResponseJson(xhr))
        }
      }
    }
    xhr.send()
  })
  return handleResponse(res)
}

export async function postData<T = any>(
  url: string,
  data?: Record<string, any> | null
) {
  const res = await new Promise<ApiResult<T>>((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    url = getFullUrl(url)
    xhr.open('POST', url)
    xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8')
    // IE 不支持 json 类型
    xhr.responseType = 'json'
    // IE9+
    if ('onload' in XMLHttpRequest.prototype) {
      xhr.onload = function () {
        resolve(getResponseJson(xhr))
      }
      xhr.onerror = function () {
        reject(new Error(`Error ${xhr.status}: ${xhr.statusText}`))
      }
    } else {
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          resolve(getResponseJson(xhr))
        }
      }
    }
    xhr.send(data && JSON.stringify(data))
  })
  return handleResponse(res)
}

async function getResponseJson(xhr: XMLHttpRequest) {
  if (xhr.status !== 200) {
    throw new Error(`Error ${xhr.status}: ${xhr.statusText}`)
  }
  // IE8 不支持
  // IE9-11 不支持返回 json 类型，其是字符串
  const res = xhr.response
  if (typeof res === 'object') {
    return res
  }
  const text = xhr.responseText
  if (text) {
    return JSON.parse(text)
  }
  throw new Error('未返回数据')
}

function handleResponse<T>(res?: ApiResult<T>) {
  if (!res || !res.code) {
    throw new Error('数据异常')
  }

  if (res.code !== '100') {
    throw new Error(res.msg)
  }

  return res.data
}

interface ApiResult<T> {
  code: string
  data: T
  msg: string
}
